//
// Created by martin on 2/24/22.
//

#include <malloc.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#include <endian.h>

#if defined(__GNUC__)
/*
 * The inline assembler code makes type blur,
 * so we disable warnings for a while.
 */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wold-style-cast"
#endif

#if 0
/* 为每个线程保存文件指针的TSD键值，根据键值可以找到线程各自的Data */
static pthread_key_t thread_log_key;

void write_to_thread_log(const char* message)
{
    FILE* thread_log = (FILE*) pthread_getspecific(thread_log_key);
    fprintf(thread_log, "%s\n", message);
}

void fn_close_thread_log(void* thread_log)
{
    fclose((FILE*)thread_log);
}

void* thread_function(void* arg)
{
    char thread_log_filename[128];
    FILE* thread_log;

    snprintf(thread_log_filename, sizeof(thread_log_filename),
             "thread%ld.log", (unsigned long)pthread_self());
    thread_log = fopen(thread_log_filename, "w");

    /* 将文件指针保存在thread_log_key标识的TSD中 */
    pthread_setspecific(thread_log_key, thread_log);

    write_to_thread_log("Thread starting.");
    return NULL;
}

int main()
{
    int i;
    pthread_t threads[5];

    pthread_key_create(&thread_log_key, fn_close_thread_log);
    for (i = 0; i < 5; ++i) {
        pthread_create(&(threads[i]), NULL, thread_function, NULL);
    }

    for (i = 0; i < 5; ++i) {
        pthread_join(threads[i], NULL);
    }
    return 0;
}
#endif

__thread FILE* thread_log = NULL;
void write_to_thread_log(const char* message)
{
    fprintf(thread_log, "%s\n", message);
}

void *thread_function(void* arg)
{
    char thread_log_filename[128];
    sprintf(thread_log_filename, "thread%ld.log", (unsigned long)pthread_self());

    thread_log = fopen(thread_log_filename, "w");
    write_to_thread_log("Thread starting.");

    fclose(thread_log);
    return NULL;
}

int main()
{
    int i;
    pthread_t threads[5];

    for (i = 0; i < 5; ++i)
        pthread_create(&(threads[i]), NULL, thread_function, NULL);
    for (i = 0; i < 5; ++i)
        pthread_join(threads[i], NULL);
    return 0;
}

#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif